From c184a240a5cfb5fc46214542a4424efd05fce745 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 21 Apr 2005 15:39:08 +0000 Subject: [PATCH] bitkeeper revision 1.1357 (4267c91c8u7H5ttS9RWRyBY5FrTm3g) Fix APIC setup on legacy systems. Signed-off-by: Keir Fraser --- xen/arch/x86/apic.c | 49 ++++++++++++++++++++++++++++++++++++-------- xen/arch/x86/setup.c | 2 +- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/xen/arch/x86/apic.c b/xen/arch/x86/apic.c index e00e403f35..f3b5c64f77 100644 --- a/xen/arch/x86/apic.c +++ b/xen/arch/x86/apic.c @@ -229,17 +229,48 @@ void __init sync_Arb_IDs(void) extern void __error_in_apic_c (void); -/* - * WAS: An initial setup of the virtual wire mode. - * NOW: We don't bother doing anything. All we need at this point - * is to receive timer ticks, so that 'jiffies' is incremented. - * If we're SMP, then we can assume BIOS did setup for us. - * If we're UP, then the APIC should be disabled (it is at reset). - * If we're UP and APIC is enabled, then BIOS is clever and has - * probably done initial interrupt routing for us. - */ void __init init_bsp_APIC(void) { + unsigned long value, ver; + + /* + * Don't do the setup now if we have a SMP BIOS as the through-I/O-APIC + * virtual wire mode might be active. + */ + if (smp_found_config || !cpu_has_apic) + return; + + value = apic_read(APIC_LVR); + ver = GET_APIC_VERSION(value); + + /* + * Do not trust the local APIC being empty at bootup. + */ + clear_local_APIC(); + + /* + * Enable APIC. + */ + value = apic_read(APIC_SPIV); + value &= ~APIC_VECTOR_MASK; + value |= APIC_SPIV_APIC_ENABLED; + + /* This bit is reserved on P4/Xeon and should be cleared */ + if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 15)) + value &= ~APIC_SPIV_FOCUS_DISABLED; + else + value |= APIC_SPIV_FOCUS_DISABLED; + value |= SPURIOUS_APIC_VECTOR; + apic_write_around(APIC_SPIV, value); + + /* + * Set up the virtual wire mode. + */ + apic_write_around(APIC_LVT0, APIC_DM_EXTINT); + value = APIC_DM_NMI; + if (!APIC_INTEGRATED(ver)) /* 82489DX */ + value |= APIC_LVT_LEVEL_TRIGGER; + apic_write_around(APIC_LVT1, value); } void __init setup_local_APIC (void) diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index e42b319fc4..8b8f8182e0 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -388,11 +388,11 @@ static void __init start_of_day(void) if ( smp_found_config ) get_smp_config(); #endif + init_apic_mappings(); /* make APICs addressable in our pagetables. */ scheduler_init(); init_IRQ(); /* installs simple interrupt wrappers. Starts HZ clock. */ trap_init(); time_init(); /* installs software handler for HZ clock. */ - init_apic_mappings(); /* make APICs addressable in our pagetables. */ arch_init_memory(); -- 2.30.2